<template>
  <app-view>
    <van-nav-bar left-text="个人信息" left-arrow :border="false" @click-left="onClickLeft" />
    <scroll-view>
      <van-form
        ref="form"
        input-align="right"
        style="background: rgba(247, 247, 247, 1)"
        @submit="onSubmit"
      >
        <!-- 改用下面的sdk图像接口 -->
        <van-field
          v-if="false"
          v-model="formData.photo"
          class="required-item"
          readonly
          label="头像"
          placeholder="选择头像"
          :rules="[{ required: true, message: '请选择头像' }]"
        >
          <template #input>
            <van-uploader
              v-model="uploader"
              :max-count="1"
              :max-size="15 * 1024 * 1024"
              :deletable="!userInfo.photo"
              :disabled="!!userInfo.photo"
              :after-read="afterRead"
              @oversize="onOversize"
            >
              <div class="uploader-icon uploader-icon-border">
                <img class="uploader-icon" :src="DefaultUserAvatar" alt="" />
              </div>
            </van-uploader>
          </template>
        </van-field>
        <van-field
          v-model="formData.photo"
          class="required-item"
          readonly
          label="头像"
          placeholder="选择头像"
          :rules="[{ required: true, message: '请选择头像' }]"
        >
          <wx-choose-image
            slot="input"
            class="uploader-icon"
            :count="1"
            :img="userAvatar"
            :show-loading="false"
            :disabled="!!userInfo.photo"
            @error-local="onErrorLocal"
            @change-local="onChangeLocal"
            @change-server="onChangeServer"
            @click.native="onImagePreview"
          />
        </van-field>
        <van-field v-model="formData.loginName" label="登录名" disabled />
        <van-field
          v-model="formData.userName"
          label="姓名"
          class="required-item"
          placeholder="请输入姓名"
          maxlength="12"
          :rules="[{ required: true, message: '请输入姓名' }]"
        />
        <van-field
          v-model="formData.sexName"
          :is-link="true"
          readonly
          class="required-item"
          label="性别"
          placeholder="选择性别"
          :rules="[{ required: true, message: '请选择性别' }]"
          @click="onPickerClick('sex')"
        />
        <van-field v-model="formData.roleName" label="角色" disabled />
        <van-field
          v-model="formData.phone"
          type="number"
          label="手机号"
          placeholder="请输入手机号"
          class="required-item"
          :disabled="!!userInfo.phone"
          :rules="[
            { required: true, message: '请输入手机号' },
            { required: true, message: '格式不正确', pattern: patternPhone }
          ]"
        />
        <click-btn text="提交" style="background: #fff" native-type="submit" />
      </van-form>
    </scroll-view>
    <!-- 选择器弹框 -->
    <van-popup v-model="showItemPicker" position="bottom" class="popup">
      <van-picker
        show-toolbar
        :default-index="pickerDefaultIndex"
        :columns="columns"
        @confirm="onPickerConfirm"
        @cancel="showItemPicker = false"
      />
    </van-popup>
  </app-view>
</template>

<script>
  import { ImagePreview } from 'vant';
  import Exif from 'exif-js';
  import { mapGetters, mapActions } from 'vuex';
  import { wxFaceUpload } from '@api/mine';
  import { findUserSex, uploadFace } from '@api/common/user';
  import ClickBtn from '@views/modules/access/components/click-btn';
  import { isEmpty } from '@utils/util';
  import DefaultUserAvatar from '@assets/images/mine/icon/default-icon@2x.png';
  import WxChooseImage from '@components/wx-choose-image/index';
  import ScrollView from '@components/scroll-view/index';
  import { phone } from '@utils/pattern';

  export default {
    components: { ScrollView, WxChooseImage, ClickBtn },
    data() {
      return {
        patternPhone: phone,
        DefaultUserAvatar,
        loading: {},
        uploader: [],
        files: {
          name: '',
          type: ''
        },
        formData: {}, // 表单数据
        columnsInfo: {
          sex: []
        },
        // [{ type: 'sex', columns: ['男', '女'] }], // 弹出框列表数据
        itemType: '', // 弹框字段的标识
        columns: [], // 展示的弹出框列表数据
        showItemPicker: false, // 是否弹出
        pickerDefaultIndex: '' // picker弹框默认选中的下标
      };
    },
    computed: {
      ...mapGetters('user', ['userInfo', 'userRoles', 'userRole']),
      userAvatar() {
        return this.formData.photo || this.userInfo.photo || DefaultUserAvatar;
      }
    },
    mounted() {
      window.vm = this;

      const info = this.userInfo;
      const role = this.userRole;

      const { roleName } = !isEmpty(role) ? role : {};

      this.formData = { ...info, roleName };
      if (info.photo) {
        this.uploader = [{ url: info.photo }];
      }

      this.findUserSex();
    },
    methods: {
      ...mapActions('user', ['updateUserInfo']),
      // -----------------图片处理的方法
      // 组件方法 获取 流
      afterRead(file) {
        this.files.name = file.file.name; // 获取文件名
        this.files.type = file.file.type; // 获取类型
        this.imgPreview(file.file);
      },
      // 处理图片
      imgPreview(file) {
        const self = this;
        let Orientation;
        // 去获取拍照时的信息，解决拍出来的照片旋转问题   npm install exif-js --save   这里需要安装一下包
        Exif.getData(file, function () {
          Orientation = Exif.getTag(this, 'Orientation');
        });
        // 看支持不支持FileReader
        if (!file || !window.FileReader) return;
        if (/^image/.test(file.type)) {
          // 创建一个reader
          const reader = new FileReader();
          // 将图片2将转成 base64 格式
          reader.readAsDataURL(file);
          // 读取成功后的回调
          reader.onloadend = function () {
            const result = this.result;
            const img = new Image();
            img.src = result;
            // 判断图片是否大于500K,是就直接上传，反之压缩图片
            if (this.result.length <= 500 * 1024) {
              // 上传图片
              self.postImg(this.result);
            } else {
              img.onload = function () {
                const data = self.compress(img, Orientation);
                // 上传图片
                self.postImg(data);
              };
            }
          };
        }
      },
      // 压缩图片
      compress(img, Orientation) {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        // 瓦片canvas
        const tCanvas = document.createElement('canvas');
        const tctx = tCanvas.getContext('2d');
        // let initSize = img.src.length;
        let width = img.width;
        let height = img.height;
        // 如果图片大于四百万像素，计算压缩比并将大小压至400万以下
        let ratio;
        if ((ratio = (width * height) / 4000000) > 1) {
          // console.log("大于400万像素");
          ratio = Math.sqrt(ratio);
          width /= ratio;
          height /= ratio;
        } else {
          ratio = 1;
        }
        canvas.width = width;
        canvas.height = height;
        //    铺底色
        ctx.fillStyle = '#fff';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        // 如果图片像素大于100万则使用瓦片绘制
        let count;
        if ((count = (width * height) / 1000000) > 1) {
          // console.log("超过100W像素");
          count = ~~(Math.sqrt(count) + 1); // 计算要分成多少块瓦片
          //      计算每块瓦片的宽和高
          const nw = ~~(width / count);
          const nh = ~~(height / count);
          tCanvas.width = nw;
          tCanvas.height = nh;
          for (let i = 0; i < count; i++) {
            for (let j = 0; j < count; j++) {
              tctx.drawImage(
                img,
                i * nw * ratio,
                j * nh * ratio,
                nw * ratio,
                nh * ratio,
                0,
                0,
                nw,
                nh
              );
              ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
            }
          }
        } else {
          ctx.drawImage(img, 0, 0, width, height);
        }
        // 修复ios上传图片的时候 被旋转的问题
        if (Orientation !== '' && Orientation !== 1) {
          switch (Orientation) {
            case 6: // 需要顺时针（向左）90度旋转
              this.rotateImg(img, 'left', canvas);
              break;
            case 8: // 需要逆时针（向右）90度旋转
              this.rotateImg(img, 'right', canvas);
              break;
            case 3: // 需要180度旋转
              this.rotateImg(img, 'right', canvas); // 转两次
              this.rotateImg(img, 'right', canvas);
              break;
          }
        }
        // 进行最小压缩
        const ndata = canvas.toDataURL('image/jpeg', 0.1);
        tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
        // console.log(ndata);
        return ndata;
      },
      // 旋转图片
      rotateImg(img, direction, canvas) {
        // 最小与最大旋转方向，图片旋转4次后回到原方向
        const min_step = 0;
        const max_step = 3;
        if (img === null) return;
        // img的高度和宽度不能在img元素隐藏后获取，否则会出错
        const height = img.height;
        const width = img.width;
        let step = 2;
        if (step === null) {
          step = min_step;
        }
        if (direction === 'right') {
          step++;
          // 旋转到原位置，即超过最大值
          step > max_step && (step = min_step);
        } else {
          step--;
          step < min_step && (step = max_step);
        }
        // 旋转角度以弧度值为参数
        const degree = (step * 90 * Math.PI) / 180;
        const ctx = canvas.getContext('2d');
        switch (step) {
          case 0:
            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img, 0, 0);
            break;
          case 1:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, 0, -height);
            break;
          case 2:
            canvas.width = width;
            canvas.height = height;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, -height);
            break;
          case 3:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, 0);
            break;
        }
      },
      // 将base64转换为文件
      dataURLtoFile(dataurl) {
        var arr = dataurl.split(',');
        var bstr = atob(arr[1]);
        var n = bstr.length;
        var u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], this.files.name, {
          type: this.files.type
        });
      },
      // 提交图片到后端
      postImg(base64) {
        const file = this.dataURLtoFile(base64);
        const formData = new window.FormData();
        formData.append('file', file);
        const loading = this.$toast.loading('正在上传，请稍后...');

        wxFaceUpload(formData)
          .then(({ success, msg, data }) => {
            this.$toast(success ? '照片上传成功' : msg);

            this.formData.photo = success ? data : '';
          })
          .finally(() => loading.clearLoading());
        // 提交图片
        // Some code
      },
      // ----------------- 图片处理的方法-end
      findUserSex() {
        const { formData } = this;

        findUserSex().then(({ success, msg, data }) => {
          if (!success) return this.$toast(msg);

          data.userSex.forEach((item) => {
            if (item.value === formData.sex) {
              this.$set(formData, 'sexName', item.text);
            }
          });

          this.columnsInfo.sex = data.userSex;
        });
      },
      /* onAfterRead({ file }) {
        const formData = new FormData();
        formData.append('file', file);

        const loading = this.$toast.loading('正在上传，请稍后...');

        wxFaceUpload(formData)
          .then(({ success, msg, data }) => {
            this.$toast(success ? '照片上传成功' : msg);

            this.formData.photo = success ? data : '';
          })
          .finally(() => loading.clearLoading());
      }, */
      onOversize() {
        this.$toast('文件大小不能超过15M');
      },
      // 后退点击
      onClickLeft() {
        this.$refs.form
          .validate()
          .then((res) => {
            this.$router.replace('/user');
          })
          .catch(() => {
            this.$toast('个人信息未填写完整');
          });
      },
      onSubmit() {
        const loading = this.$toast.loading('加载中...');

        this.updateUserInfo(this.formData)
          .then((success, msg) => {
            if (!success) return this.$toast(msg);

            this.$router.replace('/user');
          })
          .finally(() => loading.clearLoading());
      },
      // 选择项-点击
      onPickerClick(type) {
        const typeValue = this.formData[type];

        const curColumns = this.columnsInfo[type];

        if (isEmpty(curColumns)) return false;

        const columnsIndex = curColumns.findIndex((item) => item.value === typeValue);

        this.pickerDefaultIndex = columnsIndex === -1 ? 0 : columnsIndex;
        this.columns = [...curColumns];

        this.showItemPicker = true;

        this.itemType = type;
      },
      // 弹出框-确定-点击
      onPickerConfirm({ value, text }) {
        const name = this.itemType;

        this.formData[name] = value;
        this.formData[`${name}Name`] = text;
        this.showItemPicker = false;
      },
      // SDK 选取本地图片错误
      onErrorLocal(error) {
        this.loading.clearLoading();
        this.$toast(error);
      },
      // SDK 选取本地图片
      onChangeLocal() {
        this.loading = this.$toast.loading('正在上传，请稍后...');
      },
      // SDK 图片上传完成返回服务器ID
      onChangeServer(serverIds) {
        uploadFace({ mediaId: serverIds[0] })
          .then(({ success, data }) => {
            this.$toast(success ? '照片上传成功' : '人脸不合格');

            this.formData.photo = success ? data : '';
          })
          .finally(() => this.loading.clearLoading());
      },
      // 图片预览
      onImagePreview() {
        const { photo } = this.userInfo;

        if (isEmpty(photo)) return false;

        ImagePreview([photo]);
      }
    }
  };
</script>

<style scoped lang="less">
  @import '~@styles/var';
  @import '~@styles/modules/visitor/van-form';
  @import '~@styles/modules/visitor/van-popup';

  .uploader-icon {
    display: block;
    width: 80px;
    height: 80px;
    overflow: hidden;
    border-radius: 8px;
    object-fit: cover;
  }

  .van-form {
    /deep/ .required-item::before {
      display: flex;
      align-items: center;
    }

    /deep/ .van-field__label {
      display: flex;
      align-items: center;
    }

    /deep/ .van-field {
      height: auto;
    }

    /deep/ .van-field__body {
      padding: 15px 0;
    }

    /deep/ .van-uploader__wrapper--disabled {
      opacity: 1;
    }

    /deep/ .van-uploader__preview {
      margin: 0;
    }
  }

  .click-btn /deep/ .van-button {
    opacity: 1;
  }
</style>
